//
//  HJChatManager.m
//  KaiChat
//
//  Created by lx on 2023/10/20.
//

#import "HJChatManager.h"
#import "HJChatMessageModel.h"
#import "HJChatSessionModel.h"
#import "HJChatFriendModel.h"
#import "HJChatGroupModel.h"
#import "HJMessageTextDto.h"
#import "HJMessageImageDto.h"
#import "HJMessageVoiceDto.h"
#import "HJMessageVideoDto.h"
#import "HJMessageFileDto.h"
#import "HJIM.h"
#import "HJWebSocketManager.h"
#import "NSString+emoji.h"
#import "TUIDefine.h"
#import "EMVoiceConverter.h"
#import <AVFoundation/AVFoundation.h>


@implementation HJChatManager

- (void)sendMessageWithModel:(HJChatMessageModel *)messageModel begin:(void (^__nullable)(HJChatMessageModel * model))begin completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion {
    
    
    if (messageModel.messageType == HJMessageTypeText) {
        [self sendTextMessageWithModel:messageModel begin:begin completion:completion];
        return;
    }
    
    if (messageModel.messageType == HJMessageTypeImage) {
        [self sendImageMessageWithModel:messageModel begin:begin completion:completion];
        return;
    }
    
    if (messageModel.messageType == HJMessageTypeVoice) {
        [self sendVoiceMessageWithModel:messageModel begin:begin completion:completion];
        return;
    }
    
    if (messageModel.messageType == HJMessageTypeVideo) {
        [self sendVideoMessageWithModel:messageModel begin:begin completion:completion];
        return;
    }
    
}

- (void)sendTextMessageWithModel:(HJChatMessageModel *)messageModel begin:(void (^__nullable)(HJChatMessageModel * model))begin completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion {
    
    if (isEmptyString(messageModel.content)) return;
    
    dispatch_async_sql_queue(^{

        messageModel.content = [messageModel.content getLocalizableStringWithFaceContent];
        messageModel.messageType = HJMessageTypeText;
        [self setMessagePublicParameters:messageModel];
        BOOL isSuccess = [messageModel bg_saveOrUpdate];
        
        HJChatSessionModel *sessionModel = [HJChatSessionModel sessionModelWithMessageModel:messageModel];
        [self setSessionModelInfo:sessionModel messageModel:messageModel];
        [[HJIM shareIM].conversationManager addConversation:sessionModel];
        
        if (isSuccess) {
            messageModel.msgStatus = HJMessageStatusSending;
            [messageModel bg_saveOrUpdate];
            dispatch_async_main_queue(^{
                if (begin) {
                    begin(messageModel);
                }
            });
            
            HJMessageTextDto *messageDto = [HJMessageTextDto messageDtoWithMessageModel:messageModel];
            [self sendMessageWithModel:messageModel messageDto:messageDto completion:completion];
        }
    });
    
}

- (void)sendImageMessageWithModel:(HJChatMessageModel *)messageModel begin:(void (^__nullable)(HJChatMessageModel * model))begin completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion {
 
    dispatch_async_sql_queue(^{

        BOOL isNewMessage = isEmptyString(messageModel.serverMsgId);
        
        messageModel.messageType = HJMessageTypeImage;
        [self setMessagePublicParameters:messageModel];
        
        BOOL isSuccess = [messageModel bg_saveOrUpdate];
        
        if (isNewMessage) {
            HJChatSessionModel *sessionModel = [HJChatSessionModel sessionModelWithMessageModel:messageModel];
            [self setSessionModelInfo:sessionModel messageModel:messageModel];
            [[HJIM shareIM].conversationManager addConversation:sessionModel];
        }
        
        if (isSuccess) {
            
            if (!isEmptyString(messageModel.localPath)) {
                
                NSString *thumbnailPath = messageModel.thumbnailPath;
                if (isEmptyString(thumbnailPath)) {
                    thumbnailPath = getFileNameWithPathExtension(messageModel.localPath.pathExtension).tj_IMFileCachePath;
                } else {
                    thumbnailPath = messageModel.thumbnailPath.lastPathComponent.tj_IMFileCachePath;
                }
                
                UIImage *originImage = [UIImage imageWithContentsOfFile:messageModel.localPath.lastPathComponent.tj_IMFileCachePath];
                
                if (![[NSFileManager defaultManager] fileExistsAtPath:thumbnailPath]) {
                    
                    NSData *thumbnailImageData = getThumbnailWithImage(originImage, CGSizeMake(TImageMessageCell_Image_Width_Max, TImageMessageCell_Image_Height_Max));
                    if (thumbnailImageData.length > 25 * 1024) {
                        thumbnailImageData = [UIImage compressWithImage:[UIImage imageWithData:thumbnailImageData] toByte:25];
                    }
                    
                    //                    NSLog(@"thumbnailImageData.thumbsSize = %@", [TJTools convertFileSize:thumbnailImageData.length]);
                    
                    [HJTools writeImageData:thumbnailImageData toLocalPath:thumbnailPath];
                    messageModel.thumbnailPath = thumbnailPath;
                    messageModel.thumbnailImage = [UIImage imageWithData:thumbnailImageData];
                } else {
                    messageModel.thumbnailImage = [UIImage imageWithContentsOfFile:thumbnailPath];
                    messageModel.thumbnailPath = thumbnailPath;
                }
                messageModel.originalImage = originImage;
            }
            
            messageModel.msgStatus = HJMessageStatusSending;
            [messageModel bg_saveOrUpdate];
            
            dispatch_async_main_queue(^{
                if (begin) {
                    begin(messageModel);
                }
            });
            
            [self getImageThumbnailUrl:messageModel completion:^(NSError * _Nullable error) {
                [self getFileUrl:messageModel progress:^(CGFloat value) {
                    messageModel.progress = value;
                } completion:^(NSError *error) {
                    if (error) {
                        [self sendFailWithModel:messageModel error:error completion:completion];
                    } else {
                        HJMessageImageDto *messageDto = [HJMessageImageDto messageDtoWithMessageModel:messageModel];
                        messageDto.originUrl = messageModel.fileUrl;
                        messageDto.content = messageModel.thumbnailUrl ?: messageModel.fileUrl;
                        [messageModel bg_saveOrUpdate];
                        [self sendMessageWithModel:messageModel messageDto:messageDto completion:completion];
                    }
                }];
            }];
        }
    });
    
}

- (void)sendVoiceMessageWithModel:(HJChatMessageModel *)messageModel begin:(void (^__nullable)(HJChatMessageModel * model))begin completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion {
    
    dispatch_async_sql_queue(^{

        BOOL isNewMessage = isEmptyString(messageModel.serverMsgId);
        
        messageModel.messageType = HJMessageTypeVoice;
        [self setMessagePublicParameters:messageModel];
        
        BOOL isSuccess = [messageModel bg_saveOrUpdate];
        
        if (isNewMessage) {
            HJChatSessionModel *sessionModel = [HJChatSessionModel sessionModelWithMessageModel:messageModel];
            [self setSessionModelInfo:sessionModel messageModel:messageModel];
            [[HJIM shareIM].conversationManager addConversation:sessionModel];
        }
        
        if (isSuccess) {
            //语音的信息
            if (isEmptyString(messageModel.msg)) {
                NSURL *url = [NSURL fileURLWithPath:messageModel.localPath];
                AVURLAsset *audioAsset = [AVURLAsset URLAssetWithURL:url options:nil];
                int duration = ceil(CMTimeGetSeconds(audioAsset.duration));
                messageModel.msg = @{
                    @"fileSize": @(getFileSizeAtPath(messageModel.localPath)),
                    @"duration": @(duration).stringValue
                }.mj_JSONString;
            }
            
            messageModel.msgStatus = HJMessageStatusSending;
            [messageModel bg_saveOrUpdate];
            
            dispatch_async_main_queue(^{
                if (begin) {
                    begin(messageModel);
                }
            });
            
            [self getFileUrl:messageModel progress:^(CGFloat value) {
                messageModel.progress = value;
            } completion:^(NSError *error) {
                if (error) {
                    [self sendFailWithModel:messageModel error:error completion:completion];
                } else {
                    HJMessageVoiceDto *messageDto = [HJMessageVoiceDto messageDtoWithMessageModel:messageModel];
                    messageDto.content = messageModel.fileUrl;
                    [messageModel bg_saveOrUpdate];
                    [self sendMessageWithModel:messageModel messageDto:messageDto completion:completion];
                }
            }];
        }
    });
    
}

- (void)sendFileMessageWithModel:(HJChatMessageModel *)messageModel begin:(void (^__nullable)(HJChatMessageModel * model))begin completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion {
    
}

- (void)sendVideoMessageWithModel:(HJChatMessageModel *)messageModel begin:(void (^__nullable)(HJChatMessageModel * model))begin completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion {
    
}

- (void)sendMessageWithModel:(HJChatMessageModel *)messageModel messageDto:(HJMessageDto *)messageDto completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion {
    [HJWebSocketManager.shareManager sendMessageWithDto:messageDto complete:^(NSDictionary * _Nullable data, NSError * _Nullable error) {
        if (!error) {
            messageModel.serverMsgId = toString(data[@"seq_id"]);
            [self sendSucceedWithModel:messageModel completion:completion];
        } else {
            [self sendFailWithModel:messageModel error:error completion:completion];
        }
    }];
}

- (void)sendFailWithModel:(HJChatMessageModel *)messageModel error:(NSError *)error completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion{
    NSLog(@"error = %@", error);
    messageModel.msgStatus = HJMessageStatusFail;
    [messageModel bg_saveOrUpdateAsync:^(BOOL __isSuccess) {
        dispatch_async_main_queue(^{
            [[NSNotificationCenter defaultCenter] postNotificationName:updateSendMessageStatusNotification object:messageModel];
            if (completion) {
                completion(nil, error);
            }
        });
    }];
}

- (void)sendSucceedWithModel:(HJChatMessageModel *)messageModel completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion {
    messageModel.msgStatus = HJMessageStatusSucceed;
    [messageModel bg_saveOrUpdateAsync:^(BOOL __isSuccess) {
        dispatch_async_main_queue(^{
            if (completion) {
                completion(messageModel, nil);
            }
            [[NSNotificationCenter defaultCenter] postNotificationName:updateSendMessageStatusNotification object:messageModel];
        });
    }];
}

- (void)setMessagePublicParameters:(HJChatMessageModel *)messageModel {
    messageModel.unReadCount = @"0";
    
    if (messageModel.chatType == HJChatTypeGroup) {
        HJChatGroupModel *groupModel = [HJIM.shareIM.groupManager queryGroupInfoByGroupId:toString(messageModel.groupId ?: messageModel.sessionId)];
        messageModel.sessionName = groupModel.name;
        messageModel.sessionAvatar = groupModel.avatar;
        messageModel.sessionId = groupModel.groupId;
        messageModel.groupName = groupModel.name;
    } else {
        HJChatFriendModel *friendModel = [HJIM.shareIM.userManager queryFriendInfoByFriendId:toString(messageModel.receiverId)];
        messageModel.receiverNickname = friendModel.showName;
        messageModel.receiverAvatar = friendModel.avatar;
        messageModel.sessionName = messageModel.receiverNickname;
        messageModel.sessionAvatar = messageModel.receiverAvatar;
    }
    
    messageModel.msgStatus = HJMessageStatusNone;
    messageModel.senderId = HJUserInfo.userId;
    messageModel.senderAvatar = HJUserInfo.avatar;
    messageModel.senderNickname = HJUserInfo.nickname;
    
    if (messageModel.isForword) {
        messageModel.msgId = getMessageId();
        messageModel.timestamp = [NSString stringWithFormat:@"%.f", [[NSDate date] timeIntervalSince1970] * 1000];
    } else {
        messageModel.msgId = messageModel.msgId ?: getMessageId();
        messageModel.timestamp = messageModel.timestamp ?: [NSString stringWithFormat:@"%.f", [[NSDate date] timeIntervalSince1970] * 1000];
    }
}

- (void)setSessionModelInfo:(HJChatSessionModel *)sessionModel messageModel:(HJChatMessageModel *)messageModel {
    sessionModel.isSendMsg = @"1";
    if (messageModel.chatType == HJChatTypeSingle) {//设置消息免打扰, 置顶
        //        HJChatUserModel *chatUserMode = [HJIM.shareIM.userManager searchFriendByFriendId:messageModel.sessionId];
        //        sessionModel.disturb = toString(chatUserMode.disturb);
    } else if (messageModel.chatType == HJChatTypeGroup) {
        //        TJChatGroupModel *groupModel = [HJIM.shareIM.userManager searchGroupByGroupId:messageModel.groupId];
        //        sessionModel.disturb = toString(groupModel.disturb);
    }
}

- (void)sendMediaMessageWithModel:(HJChatMessageModel *)messageModel begin:(void (^__nullable)(HJChatMessageModel * model))begin completion:(void (^__nullable)(id  _Nullable response, NSError  * _Nullable error))completion  {
    
    NSString *fileName = getFileNameWithPathExtension(messageModel.fileURL.pathExtension);
    NSLog(@"fileName = %@", fileName);
    NSLog(@"messageModel.originalImage = %@", messageModel.originalImage);
    
    NSString *fileType = HJContentTypeForPathExtension(messageModel.fileURL.pathExtension);
    NSLog(@"fileType = %@", fileType);
    
    if ([fileType containsString:@"image"]) {
        NSString *localPath = fileName.tj_IMFileCachePath;//IM的要单独放一个文件夹一个用户一个文件夹后面改
        [HJTools writeImage:messageModel.originalImage toLocalPath:localPath];
        messageModel.localPath = localPath;
        [self sendImageMessageWithModel:messageModel begin:begin completion:completion];
        return;
    }
    
    if ([fileType containsString:@"video"]) {
        
        NSString *filePath = fileName.tj_IMFileCachePath;
        TJLog(@"videoPath = %@", filePath);
        
        NSError *error = nil;
        BOOL result = [[NSFileManager defaultManager] copyItemAtURL:messageModel.fileURL toURL:[NSURL fileURLWithPath:filePath] error:&error];
        TJLog(@"result = %d, error = %@", result, error);
        if (error) {
            completion(nil, error);
            return;
        }
        messageModel.localPath = filePath;
        [self sendVideoMessageWithModel:messageModel begin:begin completion:completion];
        return;
    }
    
}


- (void)getImageThumbnailUrl:(HJChatMessageModel *)messageModel completion:(void(^)(NSError * _Nullable error))completion {
    if (!messageModel.thumbnailUrl) {
        NSData *fileData = UIImageJPEGRepresentation(messageModel.thumbnailImage, 0.7);
        NSString *objectKey = getUploadFileKey(HJFileTypeImage, [NSString stringWithFormat:@"%@.%@", [NSString stringWithFormat:@"%ld", NSDate.date.timestamp].md5, messageModel.localPath.pathExtension]);
        [HJNetworking.shareNetwork uploadImageWithObejctKey:objectKey fileData:fileData  progress:nil success:^(NSDictionary * _Nonnull responseObject, id  _Nonnull data) {
            messageModel.thumbnailUrl = getUrlPath(data[@"url"]);
            completion(nil);
        } failure:^(NSError * _Nonnull error) {
            messageModel.thumbnailUrl = @"";
            completion(error);
        }];
    } else {
        completion(nil);
    }
    
}

- (void)getFileUrl:(HJChatMessageModel *)messageModel progress:(void (^)(CGFloat value))progress completion:(void(^)(NSError * _Nullable error))completion {
    
    if (messageModel.isForword && !isEmptyString(messageModel.fileUrl)) {
        progress(1);
        completion(nil);
        return;
    }
    
    NSData *fileData = nil;
    NSString *objectKey = nil;
    
    HJFileType fileType = HJFileTypeOther;
    if (messageModel.messageType == HJMessageTypeImage) {
        fileType = HJFileTypeImage;
    } else if (messageModel.messageType == HJMessageTypeVoice) {
        fileType = HJFileTypeVoice;
    } else if (messageModel.messageType == HJMessageTypeVideo) {
        fileType = HJFileTypeVideo;
    } else if (messageModel.messageType == HJMessageTypeOther) {
        fileType = HJFileTypeOther;
    }
    
    
    if (isEmptyString(messageModel.fileUrl)) {
        
        if (messageModel.messageType == HJMessageTypeVoice) {
            
            messageModel.localPath = messageModel.localPath.lastPathComponent.tj_IMFileCachePath;
            
            NSString *uploadPath = getFileNameWithPathExtension(messageModel.localPath.pathExtension);
            NSString *amrUploadPath = [[uploadPath stringByDeletingPathExtension] stringByAppendingString:@".amr"];
            NSString *armLocalPath = amrUploadPath.lastPathComponent.tj_IMFileCachePath;
            uploadPath = amrUploadPath;
            
            NSLog(@"uploadPath = %@", uploadPath);
            
            int result = [EMVoiceConverter wavToAmr:messageModel.localPath amrSavePath:armLocalPath];
            
            if (result == 0) {
                
                AVURLAsset *audioAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:armLocalPath] options:nil];
                int duration = MIN(60, ceil(CMTimeGetSeconds(audioAsset.duration)));
         
                messageModel.msg = @{
                    @"fileSize": @(getFileSizeAtPath(armLocalPath)),
                    @"duration": @(duration).stringValue
                }.mj_JSONString;
                [messageModel bg_saveOrUpdate];
                                
                objectKey = getUploadFileKey(fileType, [NSString stringWithFormat:@"%@.%@", [NSString stringWithFormat:@"%ld", NSDate.date.timestamp].md5, uploadPath.pathExtension]);
                fileData = [NSData dataWithContentsOfFile:messageModel.localPath];
                [HJNetworking.shareNetwork uploadImageWithObejctKey:objectKey fileData:fileData progress:nil success:^(NSDictionary * _Nonnull responseObject, id  _Nonnull data) {
                    messageModel.fileUrl = getUrlPath(data[@"url"]);
                    if ([[NSFileManager defaultManager] fileExistsAtPath:armLocalPath]) {
                        [[NSFileManager defaultManager] removeItemAtPath:armLocalPath error:nil];
                    }
                    completion(nil);
                } failure:^(NSError * _Nonnull error) {
                    messageModel.fileUrl = @"";
                    completion(error);
                }];
            } else {
                completion([NSError errorWithCode:-10001 errorReason:@"音频转换失败"]);
            }
            return;
        }
        
        if (messageModel.messageType == HJMessageTypeImage) {
            if (messageModel.originalImage) {
                fileData = UIImageJPEGRepresentation(messageModel.originalImage, 0.65);
            } else {
                fileData = [NSData dataWithContentsOfFile:messageModel.localPath];
            }
        } else  {
            fileData = [NSData dataWithContentsOfFile:messageModel.localPath];
        }

        objectKey = getUploadFileKey(fileType, [NSString stringWithFormat:@"%@.%@", [NSString stringWithFormat:@"%ld", NSDate.date.timestamp].md5, messageModel.localPath.pathExtension]);
        [HJNetworking.shareNetwork uploadImageWithObejctKey:objectKey fileData:fileData  progress:^(NSProgress * progress) {
            [[NSNotificationCenter defaultCenter] postNotificationName:updateChatFileUploadProgressNotification object:@{
                @"msgId": messageModel.msgId,
                @"progress": @(progress.fractionCompleted)
            }];
        } success:^(NSDictionary * _Nonnull responseObject, id  _Nonnull data) {
            messageModel.fileUrl = getUrlPath(data[@"url"]);
            completion(nil);
        } failure:^(NSError * _Nonnull error) {
            messageModel.fileUrl = @"";
            completion(error);
        }];
    } else {
        progress(1);
        completion(nil);
    }
    
}

- (void)searchGroupByKeyword:(NSString *)keyword completion:(void (^)(NSArray <HJChatGroupModel *> * _Nullable datas))completion {
    NSString * where = [NSString stringWithFormat:@"where (%@ like '%%%@%%') ",bg_sqlKey(@"name"),keyword];
    [HJChatGroupModel bg_findAsync:[HJChatGroupModel bg_tableName] where:where complete:^(NSArray * _Nullable array) {
        !completion ?: completion(array);
    }];
}

- (void)searchFriendByKeyword:(NSString *)keyword completion:(void (^)( NSArray <HJChatFriendModel *>* _Nullable datas))completion {
    NSString * where = [NSString stringWithFormat:@"where (%@ like '%%%@%%') ",bg_sqlKey(@"nickname"),keyword];
    [HJChatFriendModel bg_findAsync:[HJChatFriendModel bg_tableName] where:where complete:^(NSArray * _Nullable array) {
        !completion ?: completion(array);
    }];
}


@end
